#!/usr/bin/python2.5
# Copyright 2009 Joe LaPenna
"""Endpoints related to products."""

import datetime
import logging
import re
import os
import uuid

from google.appengine.api import datastore_errors
from google.appengine.api import users
from google.appengine.api.labs import taskqueue
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine import runtime

import model


CRASH_PAGE_SIZE = 500


class Product(webapp.RequestHandler):
  """Show information about a product, including its crashes."""

  def get(self):
    """Handle GET http method by returning a product page."""
    logging.debug('User request for: %s', self.request.path)
    product_key = self.request.path.split('/')[-1]
    product = model.Product.find(product_key)

    if product is None:
      logging.debug('product does not exist.')
      self.error(404)
      return

    # Determine where to start looking.
    next = None
    date = self.request.get('next', None)
    logging.debug('Requested date is: %s' % date)

    query = model.Crash.all().order('-date').filter('product =', product)

    # Lookup the crashes
    if date:
      # this is retarded, there is no nice python way to get a datetime from a
      # stringified datetime?
      time_tuple = [int(i) for i in re.split('[. :-]', date)]
      date = datetime.datetime(*time_tuple)

      # Add a date filter onto the query.
      query = query.filter('date <=', date)

    q = self.request.get('q', None)
    if q:
      query = query.filter('short =', q)

    tag = self.request.get('tag', None)
    if tag:
      query = query.filter('tag =', tag)

    version = self.request.get('version', None)
    if version:
      query = query.filter('version =', version)

    crashes = query.fetch(CRASH_PAGE_SIZE + 1)

    if len(crashes) == CRASH_PAGE_SIZE + 1:
      next = crashes[-1].date
      crashes = crashes[:CRASH_PAGE_SIZE]

    template_values = {
        'product': product,
        'crashes': crashes,
        'next': next,
    }
    path = os.path.join(os.path.dirname(__file__),
                                        '../templates/product.html')
    self.response.out.write(template.render(path, template_values))


class Add(webapp.RequestHandler):
  """Add a product for a given user."""

  def post(self):
    name = self.request.get('name')
    product = model.Product(
        user=model.User.find(users.get_current_user()),
        name=name, secret=uuid.uuid4().get_hex())
    product.put()
    self.redirect('/user')


class Delete(webapp.RequestHandler):
  """Remove a product for a given user by requesting a task."""

  def queue(self, product_key):
    logging.debug('Queueing a new task')
    task = taskqueue.add(url='/product_delete_task',
        params={'key': product_key})
    logging.debug('Task Name: %s', task.name)

  def post(self):
    product_key = self.request.get('key')
    logging.debug('Submitting delete request for: %s', product_key)

    product = model.Product.find(product_key)
    if product is not None:
      self.queue(product_key)

    self.redirect('/')


class DeleteTask(webapp.RequestHandler):
  """Remove a product for a given user."""

  MAX_RECORD_COUNT = 200

  def requeue(self, product_key):
    logging.debug('Queueing a new task')
    task = taskqueue.add(url='/product_delete_task',
        params={'key': product_key})
    logging.debug('Task Name: %s', task.name)

  def post(self):
    product_key = self.request.get('key')
    logging.debug('Delete product request for: %s', product_key)
    redirect_url = '/product_delete_task?key=%s' % product_key

    product = model.Product.find(product_key)
    crashes = db.GqlQuery('SELECT __key__ FROM Crash WHERE product = :1',
        product)

    logging.debug('Fetching records to delete for: %s', product_key)
    results = crashes.fetch(DeleteTask.MAX_RECORD_COUNT)
    db.delete(results)
    logging.debug('Deleted %s entries for %s', len(results), product_key)

    if len(results) > 0:
      self.requeue(product_key)
